<template>
  <div class="props-table">
    <div v-for="(item, key) in finalProps" :key="key" class="prop-item">
      <span class="label" v-if="item.text">{{ item.text }}</span>
      <div class="prop-compoent">
        <component
            v-if="item"
            :is="item.component"
            :[item.valueProp]="item.value"
            v-bind="item.extraProps"
            v-on="item.events"
        >
          <template v-if="item.option">
            <component
                :is="item.subComponent"
                v-for="(option, k) in item.option"
                :key="k"
                :value="option.value"
            >
              <!-- {{ option.text }} -->
              <render-vnode :vNode="option.text"></render-vnode>
            </component>
          </template>
        </component>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, VNode } from 'vue'
import { reduce } from 'lodash-es'
import { TextComponentProps } from 'cool-l-components'
// import { mapPropsToForms, PropsToForms } from '../propsMap'
import { mapPropsToForms, PropsToForms } from '../propsMap'
import RenderVnode from './RenderVnode'
import ColorPicker from './ColorPicker.vue'

/**
 * 渲染表单时候需要的属性
 * value原始值 和change更新后的值是一定要有的
 */
interface FormProps {
  component: string; //表单控件标签名
  subComponent?: string; //子元素标签名
  value: string; //画布控件原始值
  extraProps?: { [key: string]: any }; //扩展属性 例：a-slider的 min: 0, max: 3, step: 0.1
  text?: string; //标签控件名称文本
  option?: { text: string | VNode; value: any }[]; //子元素的文本和值的集合  例如 下拉框<select><option value>{{text}}</option></select>
  valueProp: string; //画布控件原始值的属性名称，默认是value
  eventName: string; //绑定更新事件名称 默认change
  events: { [key: string]: (e: any) => void }; //绑定事件
}

export default defineComponent({
  name: 'props-table',
  props: {
    props: {
      type: Object as PropType<TextComponentProps>,
      required: true
    }
  },
  components: {
    RenderVnode,
    ColorPicker
  },
  setup(props, context) {
    const finalProps = computed(() => {
      console.log('finalProps')
      //根据画布控件元素的属性TextComponentProps，来确定表单控件渲染需要的属性（必须是已在mapPropsToForms中定义的）
      return reduce(
          props.props,
          (result, value, key) => {
            const newkey = key as keyof TextComponentProps
            const item = mapPropsToForms[newkey]
            if (item) {
              const {
                valueProp = 'value',
                eventName = 'change',
                initalTransform,
                afterTransform
              } = item
              //value，valueProp，eventName，events必选属性
              const newItem: FormProps = {
                ...item, //解构item，如果item中存在以上必选属性，后边的同名属性会将其覆盖掉
                value: initalTransform ? initalTransform(value) : value,
                valueProp,
                eventName,
                events: {
                  [eventName]: (e: any) => {
                    context.emit('change', {
                      key,
                      value: afterTransform ? afterTransform(e) : e
                    })
                  }
                }
              }
              result[newkey] = newItem
            }
            return result
          },
          // {} as Required<PropsToForms> //Required<T>转化为必填属性，避免提示错误
          {} as { [key: string]: FormProps }
      )
    })
    return {
      finalProps
    }
  }
})
</script>

<style scoped></style>
